package cn.hinglo.common.interceptors.base;

import cn.hinglo.common.annotation.CurrentLimiting;
import cn.hinglo.common.entity.LimitationInfo;
import cn.hinglo.common.interceptors.RateLimitManager;
import cn.hutool.core.util.StrUtil;
import com.jfinal.aop.Interceptor;
import com.jfinal.aop.Invocation;
import com.jfinal.core.Controller;

import java.lang.reflect.Method;

/**
 * @createTime: 2019/9/10 16:24
 * @author: HingLo
 * @description: 限流基类
 */
public abstract class BaseLimitationInterceptor implements Interceptor {
    /***
     * 限流管理器，单例模式
     */
    private RateLimitManager rateLimitManager = RateLimitManager.me();

    @Override
    public void intercept(Invocation inv) {
        if (RateLimitManager.enable) {
            Controller controller = inv.getController();
            Method method = inv.getMethod();
            LimitationInfo limitationInfo = new LimitationInfo();
            limitationInfo.setTarget(this.rateLimit(inv));
            if (isAnnotation(method, controller)) {
                CurrentLimiting annotation = method.getAnnotation(CurrentLimiting.class);
                if (annotation == null) {
                    annotation = controller.getClass().getAnnotation(CurrentLimiting.class);
                }
                limitationInfo.setRate(annotation.rate());
                limitationInfo.setSecond(annotation.second());
                limitationInfo.setRenderType(annotation.renderType());
                if (StrUtil.isNotBlank(annotation.renderContent())) {
                    limitationInfo.setContent(annotation.renderContent());
                }
            }
            boolean b = rateLimitManager.rateLimit(limitationInfo, controller);
            if (!b) {
                return;
            }
        }
        inv.invoke();

    }

    /**
     * 检测是否有指定的忽略注解,如果有指定的忽略注解,就不执行拦截器
     *
     * @param handlerMethod handlerMethod
     * @param controller    controller
     * @return 返回结果,
     */
    private boolean isAnnotation(Method handlerMethod, Controller controller) {
        return handlerMethod.getAnnotation(CurrentLimiting.class) != null || controller.getClass().getAnnotation(CurrentLimiting.class) != null;
    }

    /***
     * 拦截器目标设置
     * @param interceptor 拦截器
     * @return 返回结果
     */
    protected abstract String rateLimit(Invocation interceptor);


}
